﻿using System.Text;
using Basic.WxApiService.ApiInterface;
using Basic.WxApiService.Interface;
using Basic.WxApiService.WxModel.Platform;
using Basic.WxModel.PlatformBind;
using Basic.WxModel.WxPlatform;
using WeDonekRpc.CacheClient.Interface;
using WeDonekRpc.Client;
using WeDonekRpc.Helper;

namespace Basic.WxApiService.PlatformApi
{
    internal class WxPlatformApi : WxPlatformBase, IWxPlatformApi
    {
        private static readonly Uri _GetComponentToken = new Uri("https://api.weixin.qq.com/cgi-bin/component/api_component_token");
        private static readonly string _ApiQueryAuth = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth";
        private static readonly string _GetAuthorizerInfo = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info";
        private static readonly string _GetAuthorizerToken = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token";
        private static readonly string _ApiCreatePreauthcode = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode";
        private const string _MiniLoginUri = "https://api.weixin.qq.com/sns/component/jscode2session";


        private readonly ICacheController _Cache;
        public WxPlatformApi (ICacheController cache)
        {
            this._Cache = cache;
        }

        public MiniLoginRes MiniLogin (IComponentToken token, string appId, string code)
        {
            string query = string.Format("appid={0}&grant_type=authorization_code&js_code={1}", appId, code);
            return Get<MiniLoginRes>(_MiniLoginUri, token, query);
        }
        public WxAuthorization GetMerAuth (IComponentToken token, string code)
        {
            StringBuilder post = new StringBuilder();
            _ = post.Append("{");
            _ = post.AppendFormat("\"component_appid\":\"{0}\" ,\"authorization_code\": \"{1}\"", token.AppId, code);
            _ = post.Append("}");
            return PostJson<WxAuthBody>(_ApiQueryAuth, token, post.ToString()).authorization_info;
        }
        public WxMerInfo GetMerInfo (IComponentToken token, string wxAppId)
        {
            StringBuilder post = new StringBuilder();
            _ = post.Append("{");
            _ = post.AppendFormat("\"component_appid\":\"{0}\" ,\"authorizer_appid\": \"{1}\"", token.AppId, wxAppId);
            _ = post.Append("}");
            return PostJson<WxMerInfo>(_GetAuthorizerInfo, token, post.ToString());
        }
        public PreauthCode GetPreauthCode (IComponentToken comToken)
        {
            return PostJson<PreauthCode>(_ApiCreatePreauthcode, comToken, "{\"component_appid\":\"" + comToken.AppId + "\"}");
        }
        public string ApplyToken (WxPlatformDto platform, string verifyTicket)
        {
            using (RemoteLock _Lock = RemoteLock.ApplyLock(string.Concat("comToken_", platform.Id), 3, 2))
            {
                if (_Lock.GetLock())
                {
                    string name = string.Concat("WxComponentToken_", platform.AppId);
                    WxComponentToken token = this.GetComponentToken(platform, verifyTicket);
                    string tokenId = token.component_access_token;
                    _ = this._Cache.Set(name, tokenId, new TimeSpan(0, 0, token.expires_in - 5));
                    _Lock.Exit(tokenId);
                    return tokenId;
                }
                else if (_Lock.IsError)
                {
                    throw new ErrorException(_Lock.Error);
                }
                else
                {
                    return _Lock.Extend;
                }
            }
        }
        public WxComponentToken GetComponentToken (WxPlatformDto config, string verifyTicket)
        {
            StringBuilder post = new StringBuilder();
            _ = post.Append("{");
            _ = post.AppendFormat("\"component_appid\":\"{0}\" ,\"component_appsecret\":\"{1}\",\"component_verify_ticket\": \"{2}\"", config.AppId, config.AppSecret, verifyTicket);
            _ = post.Append("}");
            return PostJson<WxComponentToken>(_GetComponentToken, post);
        }

        public WxMerAuthorizerToken GetAccessToken (IComponentToken comToken, WxPlatformBindDto platform)
        {
            StringBuilder post = new StringBuilder();
            _ = post.Append("{");
            _ = post.AppendFormat("\"component_appid\":\"{0}\" ,\"authorizer_appid\":\"{1}\",\"authorizer_refresh_token\": \"{2}\"", comToken.AppId, platform.AppId, platform.RefreshToken);
            _ = post.Append("}");
            return PostJson<WxMerAuthorizerToken>(_GetAuthorizerToken, comToken, post.ToString());
        }
    }
}
